<template>
  <div style="width: 100%;overflow-y:scroll;height: calc(100vh - 72px)">
    <div class="modern-forms" style="margin-top: 120px">
      <div class="modern-container">
        <form style="text-align: left">
          <fieldset>
            <div class="mdn-group">
              <label class="field-group mdn-upload">
                <input v-model="imgpath" type="text" class="mdn-input" placeholder="no file selected" @click="selectImg" readonly>
                <label class="mdn-label">File Load</label>
                <span class="mdn-bar"></span>
                <span class="mdn-button btn-primary"> Choose Image </span>
              </label>
            </div>
            <template v-if="imgpath">
              <div class="form-row">
                <div class="col col-4">
                  <div class="mdn-group">
                    <label class="field-group mdn-upload">
                      <label class="mdn-label">Origin Image</label>
                      <img id="originImg"/>
                    </label>
                    <label class="field-group mdn-upload">
                      <label class="mdn-label">Gray Image</label>
                      <canvas id="grayImg"/>
                    </label>
                  </div>
                </div><!-- end col-4 -->
                <div class="col col-8">
                  <label class="field-group mdn-upload">
                    <label class="mdn-label">Gray Histogram</label>
                    <div id="paint"></div>
                  </label>
                </div><!-- end col-8 -->
              </div><!-- end form-row -->
            </template>
            <template v-if="processing">
              <div class="form-row">
                <div class="col col-4">
                  <div class="mdn-group">
                    <label class="field-group mdn-upload">
                      <label class="mdn-label">Equalization Image</label>
                      <canvas id="equalizationImg"/>
                    </label>
                    <label class="field-group mdn-upload">
                      <label class="mdn-label">March Image</label>
                      <canvas id="matchImg"/>
                    </label>
                  </div>
                </div><!-- end col-4 -->
                <div class="col col-8">
                  <label class="field-group mdn-upload">
                    <label class="mdn-label" id="value-range">Matching Histogram</label>
                    <div id="slide"></div>
                    <div id="slider-range"></div>
                  </label>
                </div><!-- end col-8 -->
              </div><!-- end form-row -->
            </template>
            <button v-else-if="imgpath" type="button" class="mdn-button btn-primary" style="margin-right: 30px" @click="equalizationImg">Process Image</button>
          </fieldset>
        </form>
      </div><!-- modern-container -->
    </div><!-- modern-forms -->
  </div>
</template>

<script>
import * as d3 from 'd3'
import { sliderBottom } from 'd3-simple-slider';
var mutex = true
function binarySearch(arr, low, high, key) {
  let mid
  while (low <= high) {
    if(arr[low]==key){
      return low;
    }
    if(arr[high]==key){
      return high;
    }
    mid = low + ((high - low) >> 1);
    if (arr[mid] == key) {
      return mid;
    } else if (arr[mid] > key) {
      high = mid - 1;
    } else {
      low = mid + 1;
    }
  }
  return mid;
}
export default {
  name: "c3q1",
  data(){
    return{
      imgpath:null,
      grayPixel:null,
      grayWidth:null,
      grayHeight:null,
      processing: false
    }
  },
  methods:{
    draw(data,elId) {
      const width = 300
      const height = 300
      const margin = {
        top: 10,
        bottom: 30,
        left: 60,
        right: 60
      }

      const svg = d3.select(elId)
          .append('svg')
          .attr('width', width + margin.left + margin.right)
          .attr('height', height + margin.top + margin.bottom)
          .append('g')
          .attr('transform', `translate(${ margin.left }, ${ margin.top })`)

      const max = 256
      const histogram = d3.histogram()
          // .value(d => +d.price)
          .domain([ 0, max ])
          .thresholds(127);
      const bins = histogram( data )

      const x = d3.scaleLinear()
          .domain([0, max ])
          .range([0, width])

      const y = d3.scaleLinear()
          .domain([0, d3.max(bins, d => d.length)])
          .range([height, 0])

      svg.append('g')
          .attr('transform', `translate(0, ${ height })`)
          .call(d3.axisBottom(x))

      svg.append('g')
          .call(d3.axisLeft(y))

      svg.append('g')
          .selectAll('rect')
          .data(bins)
          .enter()
          .append('g')
          .append('rect')
          .attr('x', d => x(d.x0) + 1 )
          .attr('y', d => y(d.length) )
          .attr('width', d => x(d.x1) - x(d.x0) - 1)
          .attr('height', d => height - y(d.length))
          .attr('fill', '#69b3a2')
    },
    selectImg(){
      let input = document.createElement('input');
      input.type = 'file';
      return new Promise(function (resolve) {
        input.onchange = function(ev) {
          resolve(ev.target.files[0])
          return false;
        };
        input.click();
      }).then(file=>{
        this.imgpath = file.path
        const that = this
        return new Promise(function (resolve) {
          var reader = new FileReader();
          reader.onload = function(e){
            // target.result 该属性表示目标对象的DataURL
            let img = document.getElementById('originImg')
            img.src = e.target.result
            img.onload = ()=>resolve(img)
          }
          // 传入一个参数对象即可得到基于该参数对象的文本内容
          reader.readAsDataURL(file);
        }).then(img=>{
          let canvas = document.getElementById('grayImg')
          canvas.width = img.width;
          canvas.height = img.height;
          let ctx = canvas.getContext("2d");
          ctx.drawImage(img, 0, 0);
          let imgData = ctx.getImageData(0,0,img.width,img.height)
          let Gray, R,G,B,dataset = [],len = img.width * img.height;
          for(let i = 0;i < len;i++){
            R = imgData.data[i*4]
            G = imgData.data[i*4+1]
            B = imgData.data[i*4+2]
            Gray = parseInt(R*0.299 + G*0.587 + B*0.114)
            dataset[i] = Gray
            imgData.data[i*4] = imgData.data[i*4+1] = imgData.data[i*4+2] = Gray
            imgData.data[i*4+3] = 255
          }
          ctx.clearRect(0,0,img.width,img.height);
          ctx.putImageData(imgData, 0, 0);
          this.grayPixel = dataset
          this.grayWidth = img.width
          this.grayHeight = img.height
          this.draw(dataset,'#paint')
        })
      })
    },
    equalizationImg(){
      this.processing = true
      this.$nextTick(function (){
        let canvas = document.getElementById('equalizationImg')
        let {grayWidth,grayHeight,grayPixel} = this
        canvas.width = grayWidth;
        canvas.height = grayHeight;
        let ctx = canvas.getContext("2d");
        let imgData = ctx.getImageData(0,0,grayWidth,grayHeight)
        let Gray,dataset = [],len = grayWidth * grayHeight;
        function T(nkArr,M,N,L = 256){
          let MN = M*N, sum = 0, s = []
          for(let k = 0;k < L;k++){
            sum += nkArr[k]
            s[k] = sum/MN * (L-1)
          }
          return s
        }
        let nkArr = Array(256).fill(0)
        for(let i = 0;i < len;i++) nkArr[grayPixel[i]]++
        let skArr = T(nkArr,grayWidth,grayHeight)
        for(let i = 0;i < len;i++){
          // Gray = parseInt(skArr[grayPixel[i]] * grayPixel[i])
          Gray = Math.round(skArr[grayPixel[i]])
          dataset[i] = Gray
          imgData.data[i*4] = imgData.data[i*4+1] = imgData.data[i*4+2] = Gray
          imgData.data[i*4+3] = 255
        }
        ctx.putImageData(imgData, 0, 0);
        this.draw(dataset,'#slide')
        this.matchImg()
      })
    },
    matchImg(){
      const matching = (function(interL,interR){
        let canvas = document.getElementById('matchImg')
        let {grayWidth,grayHeight,grayPixel} = this
        canvas.width = grayWidth;
        canvas.height = grayHeight;
        let ctx = canvas.getContext("2d");
        let imgData = ctx.getImageData(0,0,grayWidth,grayHeight)
        let Gray,dataset = [],len = grayWidth * grayHeight;
        function T(nkArr,M,N,L = 256){
          let MN = M*N, sum = 0, s = []
          for(let k = 0;k < L;k++){
            sum += nkArr[k]
            s[k] = sum/MN * (L-1)
          }
          return s
        }
        function G(M,N,L = 256){
          let MN = M*N, sum = 0, v = Array(256).fill(0)
          for(let k = interL;k < L;k++){
            sum += k < interR ? 1/(interR-interL) : 0
            v[k] = sum * (L-1)
          }
          return v
        }
        let nkArr = Array(256).fill(0)
        for(let i = 0;i < len;i++) nkArr[grayPixel[i]]++
        let skArr = T(nkArr,grayWidth,grayHeight),
            vkArr = G(grayWidth,grayHeight)
        function closest(r){
          let s = skArr[r]
          let z = parseInt(binarySearch(vkArr,interL,interR,s))
          let a, b, c;
          if(z===255) {
            a = Math.abs(vkArr[z-1] - s)
            b = Math.abs(vkArr[z] - s)
            return a < b ? z - 1 : z;
          }else if (z === 0){
            b = Math.abs(vkArr[z] - s)
            c = Math.abs(vkArr[z+1] - s)
            return b < c ? z : z + 1;
          }else{
            a = Math.abs(vkArr[z-1] - s)
            b = Math.abs(vkArr[z] - s)
            c = Math.abs(vkArr[z+1] - s)
            return a < c ?(a < b ? z - 1 : z) : (b < c ? z : z + 1);
          }
        }
        let zkArr = d3.range(256).map(i=>closest(i))

        for(let i = 0;i < len;i++){
          // Gray = parseInt(skArr[grayPixel[i]] * grayPixel[i])
          // Gray = closest(grayPixel[i])
          Gray = zkArr[grayPixel[i]]
          dataset[i] = Gray
          imgData.data[i*4] = imgData.data[i*4+1] = imgData.data[i*4+2] = Gray
          imgData.data[i*4+3] = 255
        }
        ctx.putImageData(imgData, 0, 0);
        this.draw(dataset,'#slide')
      }).bind(this)
      // Range
      var sliderRange = sliderBottom()
          .min(0)
          .max(255)
          .width(300)
          // .tickFormat(d3.format('.2%'))
          .ticks(5)
          .default([0, 255])
          .fill('#2196f3')
          // .on('end',val => {
          //   let container = document.getElementById('slide');
          //   container.removeChild(container.childNodes[0])
          //   matching(val[0],val[1])
          // })
          .on('onchange', val => {
            d3.select('label#value-range').text(`Matching Histogram(${parseInt(val[0])}-${parseInt(val[1])})`);
            let container = document.getElementById('slide');
            container.removeChild(container.childNodes[0])
            matching(val[0],val[1])
          });

      var gRange = d3
          .select('div#slider-range')
          .append('svg')
          .attr('width', 500)
          .attr('height', 100)
          .append('g')
          .attr('transform', 'translate(60,0)');

      gRange.call(sliderRange);

      d3.select('label#value-range').text(
          sliderRange
              .value()
              .map(d3.format('.2%'))
              .join('-')
      );
    }
  },
  mounted() {
  }
}
</script>

<style scoped>
.axis path,
.axis line{
  fill: none;
  stroke: black;
  shape-rendering: crispEdges;
}

.axis text {
  font-family: sans-serif;
  font-size: 11px;
}

.MyRect {
  fill: steelblue;
}

.MyText {
  fill: white;
  text-anchor: middle;
}

</style>